在注册完Kaggle账号后,我们就可以来试一试Kaggle上最简单的分类问题,利用当年泰坦尼克号乘客的个人信息来预测他们其中的幸存者。
下载数据集
进入Kaggle Titanic页面下载数据集,我们可以看到这里有三个csv文件
- train.csv是我们训练用数据,我们将使用这些数据建模
- test.csv是测试用数据,我们将用这些数据检验模型的准确度
- gender_submossion.csv提供给我们知道最后应该提交什么样子的文件
导入数据集
我个人习惯用Jupyter Notebook,它可以直接生成markdown模式。可以直接安装anaconda,里面就包括了Jupyter Notebook。我们要做的是首先打开Jupyter Notebook,然后在数据集同个目录里新建一个Python notebook。然后正式开始我们的代码:
1
2
3
4
5# 导入几个基本库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
1
2df=pd.read_csv('train.csv')
df.head()
我们看到这个数据集包括:
- PassengerId,乘客的序号,从第一位开始到最后一位乘客
- Survived,0表示该乘客死亡,1表示生还
- Pclass,从1到3分别表示该乘客搭乘一等舱、二等舱、三等舱
- Name,乘客的姓名,格式是:名,称谓.姓氏
- Sex,乘客的性别,female女,male男
- Age,乘客的年龄
- SibSp,该乘客的兄弟姐妹和配偶也在船上的数量
- Parch,该乘客的父母和子女也在船上的数量
- Ticket,票号
- Fare,票价
- Cabin,客舱号
- Embarked,登船港口,C = Cherbourg, Q = Queenstown, S = Southampton
几个基本的分析
训练集统计
1
df.count()
PassengerId 891
Survived 891
Pclass 891
Name 891
Sex 891
Age 714
SibSp 891
Parch 891
Ticket 891
Fare 891
Cabin 204
Embarked 889
dtype: int64
我们可以看到在训练集train.csv里一共891名乘客,其中Age,Cabin,Embarked不全,为了模型的准确度,我们最好想办法补全它们。
总体生还率
1
df['Survived'].mean()
0.3838383838383838
总体生还率是38.38%
按照客舱等级分组
1
2calss_grouping=df.groupby('Pclass').mean()
calss_grouping
<img src="http://ww1.sinaimg.cn/mw690/b66c02d5gy1fn49fz3neqj20d003tdga.jpg"/>
我们看到客舱越高级,生还率越高,有钱真好...
按客舱等级加性别分组
1
2class_sex_grouping = df.groupby(['Pclass','Sex']).mean()
class_sex_grouping
<img src="http://ww1.sinaimg.cn/mw690/b66c02d5gy1fn49intgf2j20ew0630to.jpg"/>
1
class_sex_grouping['Survived'].plot.bar()
每个客舱等级里女性生还几率较大,还是比较绅士的。
按年龄层分组
1
2
3group_by_age = pd.cut(df["Age"], np.arange(0, 90, 10))
age_grouping = df.groupby(group_by_age).mean()
age_grouping['Survived'].plot.bar()
貌似年轻的生还几率比较大。
测试集统计
1
2df_test=pd.read_csv('test.csv')
df_test.count()
PassengerId 418
Pclass 418
Name 418
Sex 418
Age 332
SibSp 418
Parch 418
Ticket 418
Fare 417
Cabin 91
Embarked 418
dtype: int64
测试集的数据缺失发生在Age,Fare和Cabin上,和训练集并不一样,这点要注意。
处理缺失数据
处理年龄
1
2
3# 不同称谓的年龄中位数
title_age_grouping=df[['Title','Age']].groupby('Title').median()
title_age_grouping.plot.bar()
1
2
3
4
5
6# 补全年龄的函数
def fill_ages(df,title_age_grouping):
for i in range(len(df.index)):
for j in range(len(title_age_grouping.index)):
if df.loc[i,'Title'] == title_age_grouping.index[j] and np.isnan(df.loc[i,'Age']):
df.loc[i,'Age']=title_age_grouping.Age[j]
处理票价
1
2
3# 不同客舱等级和称谓的票价中位数
class_title_fare_grouping=df[['Pclass','Title','Fare']].groupby(['Pclass','Title']).median()
class_title_fare_grouping.plot.bar()
1
2
3
4
5
6# 补全票价的函数
def fill_fares(df,class_title_fare_grouping):
for i in range(len(df.index)):
for j in range(len(class_title_fare_grouping.index)):
if (df.loc[i,'Pclass'], df.loc[i,'Title'])== class_title_fare_grouping.index[j] and np.isnan(df.loc[i,'Fare']):
df.loc[i,'Fare']=class_title_fare_grouping.Fare[j]
最后总体处理
- 把上面的补全年龄和票价的函数用在数据集上,
- 先将'Cabin'列drop掉,因为缺少很多数据,并且我没想到怎么样补全客舱数据,
- 将缺少数据的行用df.dropna()清理掉,
- 再将无用的行'PassengerId','Name','Ticket'列drop掉,
- 编码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22from sklearn import preprocessing
def preprocess_titanic_df(df,title_age_grouping,class_title_fare_grouping):
#copy
processed_df = df.copy()
#get titles
get_titles(processed_df)
#fill missing ages
fill_ages(processed_df,title_age_grouping)
#fill missing fares
fill_fares(processed_df,class_title_fare_grouping)
#drop cabin variable
processed_df = processed_df.drop(['Cabin'], axis=1)
#drop na
processed_df = processed_df.dropna()
#label encoder
le = preprocessing.LabelEncoder()
processed_df.Sex = le.fit_transform(processed_df.Sex)
processed_df.Embarked = le.fit_transform(processed_df.Embarked)
processed_df.Title = le.fit_transform(processed_df.Title)
processed_df = processed_df.drop(['PassengerId','Name','Ticket'],axis=1)
return processed_df
1
2processed_df = preprocess_titanic_df(df,title_age_grouping,class_title_fare_grouping)
processed_df.count()
Survived 889
Pclass 889
Sex 889
Age 889
SibSp 889
Parch 889
Fare 889
Embarked 889
Title 889
dtype: int64
最后将训练集分成80%的训练集train和20%的验证集test,注意区分这里的验证集test是已知结果的,用来验证比较各种模型。最后我们还有test.csv是未知结果的,用来最后验证准确度。
1
2
3
4
5
6
7
8
9
10
11from sklearn import model_selection
X = processed_df.drop(['Survived'], axis=1).values
y = processed_df['Survived'].values
X_train, X_test, y_train, y_test = model_selection.train_test_split(X,y,test_size=0.2)
print('X_train',X_train.shape)
print('y_train',y_train.shape)
print('X_test',X_test.shape)
print('y_test',y_test.shape)
X_train (711, 8)
y_train (711,)
X_test (178, 8)
y_test (178,)
现在数据预处理已经完成,下一步正式进入机器学习分类算法。